package com.chuangke.file.manager;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.chuangke.common.constant.FileConstants;
import com.chuangke.common.constant.Masks;
import com.chuangke.common.exception.ChuangkeException;
import com.chuangke.file.dao.FileInfoMapper;
import com.chuangke.file.model.FileInfo;
import com.chuangke.file.model.SysFilePermission;
import com.chuangke.file.service.SysFilePermissionService;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Component
public class FileAuthManager {
	
	private static final Logger logger = LoggerFactory.getLogger(FileAuthManager.class);

	@Autowired
	private FileInfoMapper fileMapper;
	@Autowired
	private SysFilePermissionService sysFilePermissionService;

	public void checkView(String userId, String dbankId) {
		if (!canDo(userId, dbankId, null, "canView")) {
			throw new ChuangkeException("没有权限");
		}
	}

	public void checkDownload(String userId, String dbankId) {
		if (!canDo(userId, dbankId, null, "canDownload")) {
			throw new ChuangkeException("没有权限");
		}
	}

	public void checkUpload(String userId, String dbankId) {
		if (!canDo(userId, dbankId, null, "canUpload")) {
			throw new ChuangkeException("没有权限");
		}
	}

	public void checkManage(String userId, String dbankId) {
		if (!canDo(userId, dbankId, null, "canManage")) {
			throw new ChuangkeException("没有权限");
		}
	}

	public void checkEdit(String userId, String dbankId) {
		if (!canDo(userId, dbankId, null, "canEdit")) {
			throw new ChuangkeException("没有权限");
		}
	}

	public void checkDelete(String userId, String dbankId) {
		if (!canDo(userId, dbankId, null, "canDelete")) {
			throw new ChuangkeException("没有权限");
		}
	}

	public void checkView(String userId, String dbankId, String fileId) {
		if (!canDo(userId, dbankId, fileId, "canView")) {
			throw new ChuangkeException("没有权限");
		}
	}

	public void checkDownload(String userId, String dbankId, String fileId) {
		if (!canDo(userId, dbankId, fileId, "canDownload")) {
			throw new ChuangkeException("没有权限");
		}
	}

	public void checkUpload(String userId, String dbankId, String fileId) {
		if (!canDo(userId, dbankId, fileId, "canUpload")) {
			throw new ChuangkeException("没有权限");
		}
	}

	public void checkManage(String userId, String dbankId, String fileId) {
		if (!canDo(userId, dbankId, fileId, "canManage")) {
			throw new ChuangkeException("没有权限");
		}
	}

	public void checkEdit(String userId, String dbankId, String fileId) {
		if (!canDo(userId, dbankId, fileId, "canEdit")) {
			throw new ChuangkeException("没有权限");
		}
	}

	public void checkDelete(String userId, String dbankId, String fileId) {
		if (!canDo(userId, dbankId, fileId, "canDelete")) {
			throw new ChuangkeException("没有权限");
		}
	}

	public boolean canView(String userId, String dbankId) {
		return canDo(userId, dbankId, null, "canView");
	}

	public boolean canDownload(String userId, String dbankId) {
		return canDo(userId, dbankId, null, "canDownload");
	}

	public boolean canUpload(String userId, String dbankId) {
		return canDo(userId, dbankId, null, "canUpload");
	}

	public boolean canManage(String userId, String dbankId) {
		return canDo(userId, dbankId, null, "canManage");
	}

	public boolean canEdit(String userId, String dbankId) {
		return canDo(userId, dbankId, null, "canEdit");
	}

	public boolean canDelete(String userId, String dbankId) {
		return canDo(userId, dbankId, null, "canDelete");
	}

	public boolean canView(String userId, String dbankId, String fileId) {
		return canDo(userId, dbankId, fileId, "canView");
	}

	public boolean canDownload(String userId, String dbankId, String fileId) {
		return canDo(userId, dbankId, fileId, "canDownload");
	}

	public boolean canUpload(String userId, String dbankId, String fileId) {
		return canDo(userId, dbankId, fileId, "canUpload");
	}

	public boolean canManage(String userId, String dbankId, String fileId) {
		return canDo(userId, dbankId, fileId, "canManage");
	}

	public boolean canEdit(String userId, String dbankId, String fileId) {
		return canDo(userId, dbankId, fileId, "canEdit");
	}

	public boolean canDelete(String userId, String dbankId, String fileId) {
		return canDo(userId, dbankId, fileId, "canDelete");
	}

	public boolean canDo(String userId, String dbankId, String fileId, String actionColumn) {
		if(FileConstants.SYSTEM_DBANK_ID.equals(dbankId)) {
			return true ;
		}
		
		List<SysFilePermission> permissionList = sysFilePermissionService.list(Masks.ALL, userId);
		permissionList = permissionList == null ? new ArrayList<>() : permissionList;
		permissionList = permissionList.stream().filter(permission -> dbankId.equals(permission.getDbankId()))
				.collect(Collectors.toList());

		// 没有授权，返回false
		if (CollectionUtils.isEmpty(permissionList)) {
			return false;
		}

        /* 如果是操作网盘的根目录，鉴权网盘权限 */
		if (StrUtil.isBlank(fileId) || FileConstants.FILE_ROOT_PARENT.equals(fileId)) {
			permissionList = permissionList.stream()
					.filter(permission -> Masks.BOOL_NO.equals(permission.getIsAuthFile()))
					.collect(Collectors.toList());
			SysFilePermission dbankPermission = CollectionUtils.isEmpty(permissionList) ? null : permissionList.get(0);
			if(dbankPermission == null) {
				return false ;
			}
			Object value = getBeanPropertyValue(dbankPermission, actionColumn);
			return Masks.BOOL_YES.equals(value);
		}

		Map<String, SysFilePermission> permissionMap = permissionList.stream().collect(Collectors.toMap(permission -> getPermisisonKey(permission.getDbankId(), permission.getIsAuthFile(), permission.getFileId()), a -> a));

		//获取当前文件及整个网盘的目录
		List<FileInfo> fileList = fileMapper
				.selectList(new QueryWrapper<FileInfo>().lambda().eq(FileInfo::getId, fileId)
						.or(i -> i.eq(FileInfo::getDbankId, dbankId).eq(FileInfo::getType, FileInfo.TYPE_DIR)));

		FileInfo currentFile = getCurrentFileInfo(fileId, fileList);

        /* 授权优先级：文件授权>上级目录授权>网盘授权 */

        /* 1、查看有没有对当前文件的授权 */
		String currentKey = getPermisisonKey(currentFile.getDbankId(), Masks.BOOL_YES, currentFile.getId());
		SysFilePermission permission = permissionMap.get(currentKey);
		if (permission != null) {
			Object value = getBeanPropertyValue(permission, actionColumn);
			return Masks.BOOL_YES.equals(value);
		}

        /* 2、查看有没有对当前文件的上级目录进行授权 */
		if (isAuthDir(permissionList)) {
			List<String> parentDirList = getParentDirs(currentFile, fileList);

            for (String s : parentDirList) {
                String parentKey = getPermisisonKey(dbankId, Masks.BOOL_YES, s);
                SysFilePermission parentPermission = permissionMap.get(parentKey);
                if (parentPermission != null) {
                    Object value = getBeanPropertyValue(parentPermission, actionColumn);
                    return Masks.BOOL_YES.equals(value);
                }
            }
		}

        /* 3、查看有没有对当前网盘的授权情况 */
		String dbankKey = getPermisisonKey(dbankId, Masks.BOOL_NO, null);
		SysFilePermission dbankPermission = permissionMap.get(dbankKey);
		if (dbankPermission != null) {
			Object value = getBeanPropertyValue(dbankPermission, actionColumn);
			return Masks.BOOL_YES.equals(value);
		}

		return false;
	}

	private FileInfo getCurrentFileInfo(String fileId, List<FileInfo> fileList) {
		List<FileInfo> tempList = fileList.stream().filter(file -> file.getId().equals(fileId))
				.collect(Collectors.toList());
		if (CollectionUtils.isEmpty(tempList)) {
			throw new ChuangkeException("未找到当前文件");
		}
		return tempList.get(0);
	}

	private String getPermisisonKey(String dbankId, String isAuthFile, String fileId) {
		return dbankId + "-" + isAuthFile + (fileId == null ? "-" : fileId);
	}

	/**
	 * 查看是否对当前网盘的目录进行过授权
	 * 
	 * @param permissionList
	 * @return
	 */
	private boolean isAuthDir(List<SysFilePermission> permissionList) {
		return permissionList.stream().anyMatch(permission -> Masks.BOOL_YES.equals(permission.getIsAuthFile())
				&& FileInfo.TYPE_DIR.equals(permission.getFileType()));
	}

	/**
	 * 寻找文件的上级目录
	 * 
	 * @param currentFile
	 * @param fileList
	 * @return
	 */
	private List<String> getParentDirs(FileInfo currentFile, List<FileInfo> fileList) {
		List<String> parentDirList = new ArrayList<>();// 上级目录id
		if (StrUtil.isNotBlank(currentFile.getParentId()) && !"0".equals(currentFile.getParentId())) {
			parentDirList.add(currentFile.getParentId());

			FileInfo parentFile = findParentDir(currentFile.getParentId(), fileList);
			while (parentFile != null) {
				parentDirList.add(parentFile.getId());
				parentFile = findParentDir(parentFile.getParentId(), fileList);
			}
		}
		return parentDirList;
	}

	private FileInfo findParentDir(String fileId, List<FileInfo> fileList) {
        for (FileInfo fileInfo : fileList) {
            if (fileId.equals(fileInfo.getId())) {
                return fileInfo;
            }
        }
		return null;
	}

	private Object getBeanPropertyValue(Object bean, String name) {
		try {
			return PropertyUtils.getNestedProperty(bean, name);
		} catch (Exception e) {
			logger.error("bean:{};name:{}",bean,name);
			throw new ChuangkeException(e);
		}
	}

}
